Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


vendor/rns_filesync/rns_filesync/service.py dev (8f381c86) Text, 39.45 KB

T8b949e"""Embeddable FileSyncService for Reticulum hosts."""

Tff7b72from T7ee787__future__ Tff7b72import Te6edf3annotations

Tff7b72import T7ee787contextlib
Tff7b72import T7ee787os
Tff7b72import T7ee787tempfile
Tff7b72import T7ee787threading
Tff7b72import T7ee787time
Tff7b72from T7ee787collectionsT7ee787.T7ee787abc Tff7b72import Te6edf3Callable
Tff7b72from T7ee787typing Tff7b72import Te6edf3Any

Tff7b72import T7ee787RNS

Tff7b72from T7ee787rns_filesync Tff7b72import Te6edf3protocol
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787constants Tff7b72import Tb4b4b4(
Te6edf3ANNOUNCE_INTERVAL_DEFAULTTb4b4b4,
Te6edf3APP_NAMETb4b4b4,
Te6edf3ASPECTTb4b4b4,
Te6edf3BLOCK_SIZETb4b4b4,
Te6edf3LINK_TIMEOUT_DEFAULTTb4b4b4,
Te6edf3PATH_TIMEOUT_DEFAULTTb4b4b4,
Te6edf3RECONNECT_BASE_INTERVALTb4b4b4,
Te6edf3RECONNECT_MAX_INTERVALTb4b4b4,
Te6edf3SCAN_INTERVALTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787inventory Tff7b72import Tb4b4b4(
Te6edf3InventoryTb4b4b4,
Te6edf3decide_sync_actionTb4b4b4,
Te6edf3differing_block_numsTb4b4b4,
Te6edf3hash_blocksTb4b4b4,
Te6edf3hash_fileTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787paths Tff7b72import Te6edf3PathJailErrorTb4b4b4, Te6edf3normalize_relpathTb4b4b4, Te6edf3resolve_under_root
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787peers Tff7b72import Tb4b4b4(
Te6edf3create_outbound_destinationTb4b4b4,
Te6edf3establish_linkTb4b4b4,
Te6edf3hex_hashTb4b4b4,
Te6edf3parse_hashTb4b4b4,
Te6edf3peer_id_from_linkTb4b4b4,
Te6edf3resolve_peer_identityTb4b4b4,
Te6edf3wait_for_pathTb4b4b4,
Tb4b4b4)
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787permissions Tff7b72import Te6edf3PermissionStore
Tff7b72from T7ee787rns_filesyncT7ee787.T7ee787transfer Tff7b72import Tb4b4b4(
Te6edf3build_delta_payloadTb4b4b4,
Te6edf3commit_received_fileTb4b4b4,
Te6edf3create_empty_fileTb4b4b4,
Tb4b4b4)


Tff7b72class T56d364FileSyncServiceTb4b4b4:
T8b949e"""Peer-to-peer directory sync over Reticulum.

Host programs inject identity and optionally an existing Reticulum instance.
The service never constructs a second Reticulum stack when one already exists.
"""

Tff7b72def Tff7b72__init__Tb4b4b4(
Tff7b72selfTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3identityTb4b4b4,
Te6edf3sync_directoryTb4b4b4: Tffa657strTb4b4b4,
Te6edf3storage_dirTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3reticulumTff7b72=Tff7b72NoneTb4b4b4,
Te6edf3configpathTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3permissionsTb4b4b4: Te6edf3PermissionStore Tff7b72| Tffa657dict Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3own_reticulumTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffidentity Tff7b72= Te6edf3identity
Tff7b72selfTff7b72.Td2a8ffsync_directory Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffrealpathTb4b4b4(Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexpanduserTb4b4b4(Te6edf3sync_directoryTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffstorage_dir Tff7b72= Te6edf3storage_dir
Tff7b72selfTff7b72.Td2a8ffconfigpath Tff7b72= Te6edf3configpath
Tff7b72selfTff7b72.Td2a8ff_provided_reticulum Tff7b72= Te6edf3reticulum
Tff7b72selfTff7b72.Td2a8ff_own_reticulum Tff7b72= Te6edf3own_reticulum
Tff7b72selfTff7b72.Td2a8ffreticulum Tff7b72= Tff7b72None

Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3permissionsTb4b4b4, Te6edf3PermissionStoreTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpermissions Tff7b72= Te6edf3permissions
Tff7b72elif Tffa657isinstanceTb4b4b4(Te6edf3permissionsTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpermissions Tff7b72= Te6edf3PermissionStoreTb4b4b4(Te6edf3permissionsTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffpermissions Tff7b72= Te6edf3PermissionStoreTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffinventory Tff7b72= Te6edf3InventoryTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Tff7b72None

Tff7b72selfTff7b72.Td2a8ff_lock Tff7b72= Te6edf3threadingTff7b72.Td2a8ffRLockTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_linksTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_desired_peersTb4b4b4: Tffa657setTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_incomingTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657floatTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_outgoingTb4b4b4: Tffa657dictTb4b4b4[Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4, Tffa657floatTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_resourcesTb4b4b4: Tffa657dictTb4b4b4[Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4]Tb4b4b4, Te6edf3AnyTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_browse_resultsTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657listTb4b4b4[Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4]Tb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_browse_eventsTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3threadingTff7b72.Td2a8ffEventTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_connect_attemptsTb4b4b4: Tffa657setTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTb4b4b4: Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Tffa657floatTb4b4b4] Tff7b72= Tb4b4b4{Tb4b4b4}

Tff7b72selfTff7b72.Td2a8ff_running Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_monitor Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_announce_interval Tff7b72= Te6edf3ANNOUNCE_INTERVAL_DEFAULT
Tff7b72selfTff7b72.Td2a8ff_stop_event Tff7b72= Te6edf3threadingTff7b72.Td2a8ffEventTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_threadsTb4b4b4: Tffa657listTb4b4b4[Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72selfTff7b72.Td2a8ffon_peer_connectedTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_peer_disconnectedTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_sync_progressTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_file_updatedTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_file_deletedTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None
Tff7b72selfTff7b72.Td2a8ffon_errorTb4b4b4: Te6edf3CallableTb4b4b4[Tb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4, Tff7b72NoneTb4b4b4] Tff7b72| Tff7b72None Tff7b72= Tff7b72None

Tff7b72def Td2a8ff_emitTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3callbackTb4b4b4: Te6edf3Callable Tff7b72| Tff7b72NoneTb4b4b4, Te6edf3payloadTb4b4b4: Tffa657dictTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3callback Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3callbackTb4b4b4(Te6edf3payloadTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFileSync callback error: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)

Tff7b72def Td2a8ff_ensure_reticulumTb4b4b4(Tff7b72selfTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffreticulum Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreticulum
Te6edf3existing Tff7b72= Tff7b72None
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3existing Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTff7b72.Td2a8ffget_instanceTb4b4b4(Tb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_provided_reticulum Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffreticulum Tff7b72= Tff7b72selfTff7b72.Td2a8ff_provided_reticulum
Tff7b72selfTff7b72.Td2a8ff_own_reticulum Tff7b72= Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreticulum
Tff7b72if Te6edf3existing Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffreticulum Tff7b72= Te6edf3existing
Tff7b72selfTff7b72.Td2a8ff_own_reticulum Tff7b72= Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreticulum
Tff7b72selfTff7b72.Td2a8ffreticulum Tff7b72= Te6edf3RNSTff7b72.Td2a8ffReticulumTb4b4b4(Tff7b72selfTff7b72.Td2a8ffconfigpathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_own_reticulum Tff7b72= Tff7b72True
Tff7b72return Tff7b72selfTff7b72.Td2a8ffreticulum

Tff7b72def Td2a8ffstartTb4b4b4(
Tff7b72selfTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3monitorTb4b4b4: Tffa657bool Tff7b72= Tff7b72TrueTb4b4b4,
Te6edf3announce_intervalTb4b4b4: Tffa657int Tff7b72= Te6edf3ANNOUNCE_INTERVAL_DEFAULTTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657strTb4b4b4:
T8b949e"""Register inbound destination and start background workers."""
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ff_runningTb4b4b4:
Tff7b72return Te6edf3hex_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)

Te6edf3osTff7b72.Td2a8ffmakedirsTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3exist_okTff7b72=Tff7b72TrueTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_ensure_reticulumTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffloadTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffscanTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Te6edf3RNSTff7b72.Td2a8ffDestinationTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffidentityTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffINTb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffDestinationTff7b72.Td2a8ffSINGLETb4b4b4,
Te6edf3APP_NAMETb4b4b4,
Te6edf3ASPECTTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffset_link_established_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_link_establishedTb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_running Tff7b72= Tff7b72True
Tff7b72selfTff7b72.Td2a8ff_monitor Tff7b72= Te6edf3monitor
Tff7b72selfTff7b72.Td2a8ff_announce_interval Tff7b72= Tffa657maxTb4b4b4(T79c0ff10Tb4b4b4, Tffa657intTb4b4b4(Te6edf3announce_intervalTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_stop_eventTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffFileSync started dest=Tffd700{Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)Tffd700}Ta5d6ff Ta5d6ff"
Ta5d6fffTa5d6ff"Ta5d6ffid=Tffd700{Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffhashTb4b4b4)Tffd700}Ta5d6ff dir=Tffd700{Tff7b72selfTff7b72.Td2a8ffsync_directoryTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_NOTICETb4b4b4,
Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_threads Tff7b72= Tb4b4b4[
Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(
Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ff_announce_loopTb4b4b4,
Te6edf3nameTff7b72=Ta5d6ff"Ta5d6fffilesync-announceTa5d6ff"Tb4b4b4,
Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)Tb4b4b4,
Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(
Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ff_reconnect_loopTb4b4b4,
Te6edf3nameTff7b72=Ta5d6ff"Ta5d6fffilesync-reconnectTa5d6ff"Tb4b4b4,
Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4]
Tff7b72if Te6edf3monitorTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_threadsTff7b72.Td2a8ffappendTb4b4b4(
Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(
Te6edf3targetTff7b72=Tff7b72selfTff7b72.Td2a8ff_monitor_loopTb4b4b4,
Te6edf3nameTff7b72=Ta5d6ff"Ta5d6fffilesync-monitorTa5d6ff"Tb4b4b4,
Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3thread Tff7b72in Tff7b72selfTff7b72.Td2a8ff_threadsTb4b4b4:
Te6edf3threadTff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)

Tff7b72return Te6edf3hex_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)

Tff7b72def Td2a8ffstopTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e"""Tear down links, destination, and worker threads."""
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_runningTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_running Tff7b72= Tff7b72False
Tff7b72selfTff7b72.Td2a8ff_stop_eventTff7b72.Td2a8ffsetTb4b4b4(Tb4b4b4)

Te6edf3links Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffclearTb4b4b4(Tb4b4b4)
Te6edf3dest Tff7b72= Tff7b72selfTff7b72.Td2a8ffdestination
Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72= Tff7b72None

Tff7b72for Te6edf3link Tff7b72in Te6edf3linksTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3linkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3dest Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8ffTransportTff7b72.Td2a8ffderegister_destinationTb4b4b4(Te6edf3destTb4b4b4)

Tff7b72for Te6edf3thread Tff7b72in Tff7b72selfTff7b72.Td2a8ff_threadsTb4b4b4:
Te6edf3threadTff7b72.Td2a8ffjoinTb4b4b4(Te6edf3timeoutTff7b72=T79c0ff2.0Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_threads Tff7b72= Tb4b4b4[Tb4b4b4]
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffFileSync stoppedTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)

Tff7b72def Td2a8ffget_statusTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3peers Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTb4b4b4)
Te6edf3files Tff7b72= Tffa657lenTb4b4b4(Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsnapshotTb4b4b4(Tb4b4b4)Tb4b4b4)
Te6edf3dest Tff7b72= Te6edf3hex_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4) Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72else Tff7b72None
Te6edf3identity Tff7b72= Te6edf3hex_hashTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentityTff7b72.Td2a8ffhashTb4b4b4)
Te6edf3running Tff7b72= Tff7b72selfTff7b72.Td2a8ff_running
Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffrunningTa5d6ff"Tb4b4b4: Te6edf3runningTb4b4b4,
Ta5d6ff"Ta5d6ffsync_directoryTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4,
Ta5d6ff"Ta5d6ffidentity_hashTa5d6ff"Tb4b4b4: Te6edf3identityTb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Te6edf3destTb4b4b4,
Ta5d6ff"Ta5d6ffpeersTa5d6ff"Tb4b4b4: Te6edf3peersTb4b4b4,
Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4: Te6edf3filesTb4b4b4,
Ta5d6ff"Ta5d6ffwhitelistTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabledTb4b4b4,
Ta5d6ff"Ta5d6ffmonitorTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ff_monitorTb4b4b4,
Tb4b4b4}

Tff7b72def Td2a8fflist_peersTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4]Tb4b4b4:
Te6edf3result Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3items Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3peer_idTb4b4b4, Te6edf3link Tff7b72in Te6edf3itemsTb4b4b4:
Te6edf3resultTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3peer_idTb4b4b4,
Ta5d6ff"Ta5d6ffdestination_hashTa5d6ff"Tb4b4b4: Te6edf3hex_hashTb4b4b4(Te6edf3linkTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffstatusTa5d6ff"Tb4b4b4: Te6edf3linkTff7b72.Td2a8ffstatusTb4b4b4,
Ta5d6ff"Ta5d6ffpermissionsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3result

Tff7b72def Td2a8fflist_filesTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4]Tb4b4b4:
Te6edf3snap Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsnapshotTb4b4b4(Tb4b4b4)
Tff7b72return Tb4b4b4[
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3pathTb4b4b4,
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffmtimeTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmtimeTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}
Tff7b72for Te6edf3pathTb4b4b4, Te6edf3info Tff7b72in Tffa657sortedTb4b4b4(Te6edf3snapTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)
Tb4b4b4]

Tff7b72def Td2a8ffannounce_nowTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffconnect_peerTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657str Tff7b72| Tffa657bytesTb4b4b4,
Te6edf3timeoutTb4b4b4: Tffa657float Tff7b72= Te6edf3PATH_TIMEOUT_DEFAULTTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4:
T8b949e"""Connect using identity hash (destination hash accepted as fallback)."""
Te6edf3peer_hash Tff7b72= Te6edf3parse_hashTb4b4b4(Te6edf3identity_hashTb4b4b4)
Te6edf3peer_hex Tff7b72= Te6edf3hex_hashTb4b4b4(Te6edf3peer_hashTb4b4b4)

Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72for Te6edf3pidTb4b4b4, Te6edf3link Tff7b72in Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffHANDSHAKETb4b4b4) Tff7b72and Tb4b4b4(
Te6edf3pid Tff7b72== Te6edf3peer_hex Tff7b72or Te6edf3hex_hashTb4b4b4(Te6edf3linkTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffhashTb4b4b4) Tff7b72== Te6edf3peer_hex
Tb4b4b4)Tb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3pidTb4b4b4, Ta5d6ff"Ta5d6ffreusedTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4}

Te6edf3identityTb4b4b4, Te6edf3how Tff7b72= Te6edf3resolve_peer_identityTb4b4b4(Te6edf3peer_hashTb4b4b4)
Tff7b72if Te6edf3identity Tff7b72is Tff7b72NoneTb4b4b4:
T8b949e# Path request may populate known destinations for destination hashes.
Te6edf3wait_for_pathTb4b4b4(Te6edf3peer_hashTb4b4b4, Te6edf3timeoutTff7b72=Tffa657minTb4b4b4(Te6edf3timeoutTb4b4b4, T79c0ff5.0Tb4b4b4)Tb4b4b4)
Te6edf3identityTb4b4b4, Te6edf3how Tff7b72= Te6edf3resolve_peer_identityTb4b4b4(Te6edf3peer_hashTb4b4b4)
Tff7b72if Te6edf3identity Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffcould not recall identity for Tffd700{Te6edf3peer_hexTffd700}Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_errorTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}Tb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}

Te6edf3destination Tff7b72= Te6edf3create_outbound_destinationTb4b4b4(Te6edf3identityTb4b4b4)
Tff7b72if Tff7b72not Te6edf3wait_for_pathTb4b4b4(Te6edf3destinationTff7b72.Td2a8ffhashTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffpath timeout for Tffd700{Te6edf3peer_hexTffd700}Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_errorTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}Tb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}

Te6edf3link Tff7b72= Te6edf3establish_linkTb4b4b4(
Te6edf3destinationTb4b4b4,
Te6edf3established_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ff_on_link_establishedTb4b4b4,
Te6edf3closed_callbackTff7b72=Tff7b72selfTff7b72.Td2a8ff_on_link_closedTb4b4b4,
Te6edf3timeoutTff7b72=Te6edf3LINK_TIMEOUT_DEFAULTTb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3link Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3msg Tff7b72= Ta5d6fffTa5d6ff"Ta5d6fflink failed for Tffd700{Te6edf3peer_hexTffd700}Ta5d6ff"
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_errorTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}Tb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Te6edf3msgTb4b4b4}

T8b949e# Reveal our identity to the remote so inbound ACL and peer slots work.
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3linkTff7b72.Td2a8ffidentifyTb4b4b4(Tff7b72selfTff7b72.Td2a8ffidentityTb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_configure_linkTb4b4b4(Te6edf3linkTb4b4b4)
Te6edf3peer_id Tff7b72= Te6edf3peer_id_from_linkTb4b4b4(Te6edf3linkTb4b4b4) Tff7b72or Te6edf3hex_hashTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_linksTb4b4b4[Te6edf3peer_idTb4b4b4] Tff7b72= Te6edf3link
Tff7b72selfTff7b72.Td2a8ff_desired_peersTff7b72.Td2a8ffaddTb4b4b4(Te6edf3hex_hashTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTff7b72.Td2a8ffpopTb4b4b4(Te6edf3hex_hashTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4, Tff7b72NoneTb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_maybe_exchange_listsTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3peer_idTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffConnected to peer Tffd700{Te6edf3peer_idTffd700}Ta5d6ff via Tffd700{Te6edf3howTffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4,
Tb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3peer_idTb4b4b4, Ta5d6ff"Ta5d6ffviaTa5d6ff"Tb4b4b4: Te6edf3howTb4b4b4}

Tff7b72def Td2a8ffdisconnect_peerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3peer_idTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3link Tff7b72= Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffpopTb4b4b4(Te6edf3peer_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_desired_peersTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3peer_idTb4b4b4)
Tff7b72if Te6edf3link Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3linkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ffbrowse_peerTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3peer_idTb4b4b4: Tffa657strTb4b4b4, Te6edf3timeoutTb4b4b4: Tffa657float Tff7b72= T79c0ff10.0Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4]Tb4b4b4:
Te6edf3link Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_linkTb4b4b4(Te6edf3peer_idTb4b4b4)
Tff7b72if Te6edf3link Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tb4b4b4[Tb4b4b4]
Te6edf3event Tff7b72= Te6edf3threadingTff7b72.Td2a8ffEventTb4b4b4(Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_browse_eventsTb4b4b4[Te6edf3peer_idTb4b4b4] Tff7b72= Te6edf3event
Tff7b72selfTff7b72.Td2a8ff_browse_resultsTff7b72.Td2a8ffpopTb4b4b4(Te6edf3peer_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3protocolTff7b72.Td2a8ffmake_file_list_requestTb4b4b4(Te6edf3browserTff7b72=Tff7b72TrueTb4b4b4)Tb4b4b4)
Te6edf3eventTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3timeoutTff7b72=Te6edf3timeoutTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_browse_eventsTff7b72.Td2a8ffpopTb4b4b4(Te6edf3peer_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72return Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_browse_resultsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4, Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ffdownload_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3peer_idTb4b4b4: Tffa657strTb4b4b4, Te6edf3pathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4[Tffa657strTb4b4b4, Te6edf3AnyTb4b4b4]Tb4b4b4:
Te6edf3link Tff7b72= Tff7b72selfTff7b72.Td2a8ff_get_linkTb4b4b4(Te6edf3peer_idTb4b4b4)
Tff7b72if Te6edf3link Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffpeer not connectedTa5d6ff"Tb4b4b4}
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72except Te6edf3PathJailError Tff7b72as Te6edf3excTb4b4b4:
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72FalseTb4b4b4, Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4}
Tff7b72selfTff7b72.Td2a8ff_request_fileTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72return Tb4b4b4{Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4: Tff7b72TrueTb4b4b4, Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4}

Tff7b72def Td2a8ff_get_linkTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3peer_idTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3link Tff7b72= Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4)
Tff7b72if Te6edf3link Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72== Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tff7b72return Te6edf3link
Tff7b72for Te6edf3pidTb4b4b4, Te6edf3candidate Tff7b72in Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3pidTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3peer_idTb4b4b4) Tff7b72or Te6edf3peer_idTff7b72.Td2a8ffstartswithTb4b4b4(Te6edf3pidTb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3candidateTff7b72.Td2a8ffstatus Tff7b72== Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tff7b72return Te6edf3candidate
Tff7b72return Tff7b72None

Tff7b72def Td2a8ff_peer_keyTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tffa657str Tff7b72| Tff7b72NoneTb4b4b4:
Tff7b72return Te6edf3peer_id_from_linkTb4b4b4(Te6edf3linkTb4b4b4)

Tff7b72def Td2a8ff_require_permTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3permissionTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Return True if the peer may perform permission (or ACL is open)."""
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabledTb4b4b4:
Tff7b72return Tff7b72True
Te6edf3peer_id Tff7b72= Tff7b72selfTff7b72.Td2a8ff_peer_keyTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72if Tff7b72not Te6edf3peer_idTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffcheckTb4b4b4(Te6edf3peer_idTb4b4b4, Te6edf3permissionTb4b4b4)

Tff7b72def Td2a8ff_configure_linkTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3linkTff7b72.Td2a8ffset_packet_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_packetTb4b4b4)
Te6edf3linkTff7b72.Td2a8ffset_resource_strategyTb4b4b4(Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACCEPT_APPTb4b4b4)
Te6edf3linkTff7b72.Td2a8ffset_resource_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_resource_advertTb4b4b4)
Te6edf3linkTff7b72.Td2a8ffset_resource_started_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_resource_startedTb4b4b4)
Te6edf3linkTff7b72.Td2a8ffset_resource_concluded_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_resource_concludedTb4b4b4)
Tff7b72if Tff7b72not Tffa657hasattrTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffupload_buffersTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3linkTff7b72.Td2a8ffupload_buffers Tff7b72= Tb4b4b4{Tb4b4b4}

Tff7b72def Td2a8ff_on_link_establishedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3remote Tff7b72= Tff7b72None
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3remote Tff7b72= Te6edf3linkTff7b72.Td2a8ffget_remote_identityTb4b4b4(Tb4b4b4)

Tff7b72if Te6edf3remote Tff7b72is Tff7b72NoneTb4b4b4:
T8b949e# Never key inbound links by local destination hash: that collapses
T8b949e# every unidentified peer onto one _links entry.
Te6edf3linkTff7b72.Td2a8ffset_remote_identified_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_remote_identifiedTb4b4b4)
Te6edf3linkTff7b72.Td2a8ffset_link_closed_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_link_closedTb4b4b4)
Tff7b72if Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabledTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_activate_peer_linkTb4b4b4(Te6edf3linkTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72return

Tff7b72if Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabled Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffcan_connectTb4b4b4(Te6edf3remoteTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffRejecting peer Tffd700{Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3remoteTff7b72.Td2a8ffhashTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4,
Tb4b4b4)
Te6edf3linkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)
Tff7b72return

Tff7b72selfTff7b72.Td2a8ff_activate_peer_linkTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3remoteTb4b4b4)

Tff7b72def Td2a8ff_on_remote_identifiedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3identityTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabled Tff7b72and Tff7b72not Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffcan_connectTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffRejecting identified peer Tffd700{Te6edf3RNSTff7b72.Td2a8ffprettyhexrepTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4,
Tb4b4b4)
Te6edf3linkTff7b72.Td2a8ffteardownTb4b4b4(Tb4b4b4)
Tff7b72return
Te6edf3real_id Tff7b72= Te6edf3hex_hashTb4b4b4(Te6edf3identityTff7b72.Td2a8ffhashTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3had_link Tff7b72= Tffa657anyTb4b4b4(Te6edf3value Tff7b72is Te6edf3link Tff7b72for Te6edf3value Tff7b72in Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3keyTb4b4b4, Te6edf3value Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3value Tff7b72is Te6edf3link Tff7b72and Te6edf3key Tff7b72!= Te6edf3real_idTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffpopTb4b4b4(Te6edf3keyTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_linksTb4b4b4[Te6edf3real_idTb4b4b4] Tff7b72= Te6edf3link
Tff7b72selfTff7b72.Td2a8ff_desired_peersTff7b72.Td2a8ffaddTb4b4b4(Te6edf3real_idTb4b4b4)
Tff7b72if Te6edf3had_linkTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_configure_linkTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_peer_connectedTb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3real_idTb4b4b4,
Ta5d6ff"Ta5d6ffpermissionsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3real_idTb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_maybe_exchange_listsTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3real_idTb4b4b4)
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_activate_peer_linkTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3identityTb4b4b4)

Tff7b72def Td2a8ff_activate_peer_linkTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3remoteTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_configure_linkTb4b4b4(Te6edf3linkTb4b4b4)
Te6edf3peer_id Tff7b72= Te6edf3peer_id_from_linkTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72if Te6edf3peer_id Tff7b72is Tff7b72None Tff7b72and Te6edf3remote Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Te6edf3peer_id Tff7b72= Te6edf3hex_hashTb4b4b4(Te6edf3remoteTff7b72.Td2a8ffhashTb4b4b4)
Te6edf3provisional Tff7b72= Tff7b72False
Tff7b72if Te6edf3peer_id Tff7b72is Tff7b72NoneTb4b4b4:
T8b949e# Unique until remote identity arrives. Do not use destination.hash.
Te6edf3peer_id Tff7b72= Ta5d6fffTa5d6ff"Ta5d6ffpending:Tffd700{Tffa657idTb4b4b4(Te6edf3linkTb4b4b4)Tffd700}Ta5d6ff"
Te6edf3provisional Tff7b72= Tff7b72True
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3linkTff7b72.Td2a8ffset_remote_identified_callbackTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_on_remote_identifiedTb4b4b4)

Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72for Te6edf3keyTb4b4b4, Te6edf3value Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3value Tff7b72is Te6edf3link Tff7b72and Te6edf3key Tff7b72!= Te6edf3peer_idTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffpopTb4b4b4(Te6edf3keyTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_linksTb4b4b4[Te6edf3peer_idTb4b4b4] Tff7b72= Te6edf3link
Tff7b72if Te6edf3remote Tff7b72is Tff7b72not Tff7b72None Tff7b72and Tff7b72not Te6edf3provisionalTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_desired_peersTff7b72.Td2a8ffaddTb4b4b4(Te6edf3hex_hashTb4b4b4(Te6edf3remoteTff7b72.Td2a8ffhashTb4b4b4)Tb4b4b4)

Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_peer_connectedTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3peer_idTb4b4b4, Ta5d6ff"Ta5d6ffpermissionsTa5d6ff"Tb4b4b4: Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4)Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3provisionalTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_maybe_exchange_listsTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3peer_idTb4b4b4)

Tff7b72def Td2a8ff_on_link_closedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3peer_id Tff7b72= Te6edf3peer_id_from_linkTb4b4b4(Te6edf3linkTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3peer_id Tff7b72and Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4) Tff7b72is Te6edf3linkTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffpopTb4b4b4(Te6edf3peer_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72for Te6edf3keyTb4b4b4, Te6edf3value Tff7b72in Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3value Tff7b72is Te6edf3linkTb4b4b4:
Te6edf3peer_id Tff7b72= Te6edf3key
Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffpopTb4b4b4(Te6edf3keyTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72break
Tff7b72if Te6edf3peer_idTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_peer_disconnectedTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3peer_idTb4b4b4}Tb4b4b4)

Tff7b72def Td2a8ff_maybe_exchange_listsTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3peer_idTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3allow Tff7b72= Tb4b4b4(Tff7b72not Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabledTb4b4b4) Tff7b72or Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffcheckTb4b4b4(
Te6edf3peer_idTb4b4b4,
Ta5d6ff"Ta5d6ffreadTa5d6ff"Tb4b4b4,
Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3allowTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffSkipping file list for Tffd700{Te6edf3peer_idTffd700}Ta5d6ff: no read permissionTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4,
Tb4b4b4)
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_send_file_listTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3browserTff7b72=Tff7b72FalseTb4b4b4)
Te6edf3timeTff7b72.Td2a8ffsleepTb4b4b4(T79c0ff0.05Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3protocolTff7b72.Td2a8ffmake_file_list_requestTb4b4b4(Te6edf3browserTff7b72=Tff7b72FalseTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ff_sendTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3payloadTb4b4b4: Tffa657bytesTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3packet Tff7b72= Te6edf3RNSTff7b72.Td2a8ffPacketTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3payloadTb4b4b4)
Te6edf3packetTff7b72.Td2a8ffsendTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffPacket send failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72def Td2a8ff_send_file_listTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3browserTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffreadTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffDenied file list: no read permissionTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4)
Tff7b72return
Te6edf3files Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffscanTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3protocolTff7b72.Td2a8ffmake_file_listTb4b4b4(Te6edf3filesTb4b4b4, Te6edf3browserTff7b72=Te6edf3browserTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ff_on_packetTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3messageTb4b4b4, Te6edf3packetTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3data Tff7b72= Te6edf3protocolTff7b72.Td2a8ffdecode_messageTb4b4b4(Te6edf3messageTb4b4b4)
Tff7b72except Te6edf3protocolTff7b72.Td2a8ffProtocolError Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffBad protocol message: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)
Tff7b72return

Te6edf3link Tff7b72= Te6edf3packetTff7b72.Td2a8fflink
Te6edf3msg_type Tff7b72= Te6edf3dataTb4b4b4[Ta5d6ff"Ta5d6fftypeTa5d6ff"Tb4b4b4]
Tff7b72if Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_FILE_LISTTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_file_listTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_FILE_LIST_REQUESTTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_send_file_listTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3browserTff7b72=Tffa657boolTb4b4b4(Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbrowserTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)Tb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_FILE_REQUESTTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_file_requestTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_DELTA_REQUESTTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_delta_requestTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_EMPTY_FILETb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_empty_fileTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_FILE_UPDATETb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_file_updateTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72elif Te6edf3msg_type Tff7b72== Te6edf3protocolTff7b72.Td2a8ffMSG_FILE_DELETIONTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_handle_file_deletionTb4b4b4(Te6edf3dataTb4b4b4, Te6edf3linkTb4b4b4)

Tff7b72def Td2a8ff_handle_file_listTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
T8b949e# Inbound inventory drives local writes. Require write when ACL is on.
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffwriteTa5d6ff"Tb4b4b4)Tb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6ff"Ta5d6ffIgnored peer file list: no write permissionTa5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4)
Tff7b72return

Te6edf3peer_files Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilesTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3browser Tff7b72= Tffa657boolTb4b4b4(Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffbrowserTa5d6ff"Tb4b4b4, Tff7b72FalseTb4b4b4)Tb4b4b4)
Te6edf3peer_id Tff7b72= Tff7b72selfTff7b72.Td2a8ff_peer_keyTb4b4b4(Te6edf3linkTb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffunknownTa5d6ff"

Tff7b72if Te6edf3browserTb4b4b4:
Te6edf3remote Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3pathTb4b4b4, Te6edf3info Tff7b72in Te6edf3peer_filesTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3pathTb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72continue
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3infoTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72continue
Te6edf3remoteTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4, T79c0ff0Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffmtimeTa5d6ff"Tb4b4b4: Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmtimeTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_browse_resultsTb4b4b4[Te6edf3peer_idTb4b4b4] Tff7b72= Te6edf3remote
Te6edf3event Tff7b72= Tff7b72selfTff7b72.Td2a8ff_browse_eventsTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4)
Tff7b72if Te6edf3eventTb4b4b4:
Te6edf3eventTff7b72.Td2a8ffsetTb4b4b4(Tb4b4b4)
Tff7b72return

Te6edf3local Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffscanTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3filepathTb4b4b4, Te6edf3peer_info Tff7b72in Te6edf3peer_filesTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3peer_infoTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6fffTa5d6ff"Ta5d6ffRejected unsafe path from peer: Tffd700{Te6edf3filepathTffd700!r}Ta5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4,
Tb4b4b4)
Tff7b72continue
Te6edf3action Tff7b72= Te6edf3decide_sync_actionTb4b4b4(Te6edf3localTff7b72.Td2a8ffgetTb4b4b4(Te6edf3safeTb4b4b4)Tb4b4b4, Te6edf3peer_infoTb4b4b4)
Tff7b72if Te6edf3action Tff7b72== Ta5d6ff"Ta5d6ffrequest_fullTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_request_fileTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72elif Te6edf3action Tff7b72== Ta5d6ff"Ta5d6ffrequest_deltaTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_request_deltaTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)

Tff7b72def Td2a8ff_request_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3filepathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3filepath Tff7b72in Tff7b72selfTff7b72.Td2a8ff_incomingTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_incomingTb4b4b4[Te6edf3filepathTb4b4b4] Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3protocolTff7b72.Td2a8ffmake_file_requestTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)

Tff7b72def Td2a8ff_request_deltaTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3filepathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3filepath Tff7b72in Tff7b72selfTff7b72.Td2a8ff_incomingTb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_incomingTb4b4b4[Te6edf3filepathTb4b4b4] Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3full_path Tff7b72= Te6edf3resolve_under_rootTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3filepathTb4b4b4)
Te6edf3local_blocks Tff7b72= Te6edf3hash_blocksTb4b4b4(Te6edf3full_pathTb4b4b4) Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3full_pathTb4b4b4) Tff7b72else Tb4b4b4[Tb4b4b4]
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_incomingTff7b72.Td2a8ffpopTb4b4b4(Te6edf3filepathTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72return
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(
Te6edf3linkTb4b4b4,
Te6edf3protocolTff7b72.Td2a8ffmake_delta_requestTb4b4b4(Te6edf3filepathTb4b4b4, Tb4b4b4[Te6edf3bTb4b4b4[Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4] Tff7b72for Te6edf3b Tff7b72in Te6edf3local_blocksTb4b4b4]Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ff_begin_outgoingTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3linkTb4b4b4, Te6edf3filepathTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e# Never collapse concurrent sends onto a shared "unknown" key.
Te6edf3peer_id Tff7b72= Tff7b72selfTff7b72.Td2a8ff_peer_keyTb4b4b4(Te6edf3linkTb4b4b4) Tff7b72or Ta5d6fffTa5d6ff"Ta5d6fflink:Tffd700{Tffa657idTb4b4b4(Te6edf3linkTb4b4b4)Tffd700}Ta5d6ff"
Te6edf3key Tff7b72= Tb4b4b4(Te6edf3peer_idTb4b4b4, Te6edf3filepathTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3started Tff7b72= Tff7b72selfTff7b72.Td2a8ff_outgoingTff7b72.Td2a8ffgetTb4b4b4(Te6edf3keyTb4b4b4)
Tff7b72if Te6edf3started Tff7b72is Tff7b72not Tff7b72None Tff7b72and Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3started Tff7b72< T79c0ff86400Tb4b4b4:
Tff7b72return Tff7b72None
Tff7b72selfTff7b72.Td2a8ff_outgoingTb4b4b4[Te6edf3keyTb4b4b4] Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72return Te6edf3key

Tff7b72def Td2a8ff_end_outgoingTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3keyTb4b4b4: Tffa657tupleTb4b4b4[Tffa657strTb4b4b4, Tffa657strTb4b4b4] Tff7b72| Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3key Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_outgoingTff7b72.Td2a8ffpopTb4b4b4(Te6edf3keyTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_resourcesTff7b72.Td2a8ffpopTb4b4b4(Te6edf3keyTb4b4b4, Tff7b72NoneTb4b4b4)

Tff7b72def Td2a8ff_handle_file_requestTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3filepathTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffreadTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Te6edf3full_path Tff7b72= Te6edf3resolve_under_rootTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72return

Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3full_pathTb4b4b4)Tb4b4b4:
Tff7b72return

Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_begin_outgoingTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72if Te6edf3key Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return

Te6edf3file_size Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3full_pathTb4b4b4)
Te6edf3file_hash Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffgetTb4b4b4(Te6edf3safeTb4b4b4)
Te6edf3digest Tff7b72= Te6edf3file_hashTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4) Tff7b72if Te6edf3file_hash Tff7b72else Te6edf3hash_fileTb4b4b4(Te6edf3full_pathTb4b4b4)

Tff7b72if Te6edf3file_size Tff7b72== T79c0ff0Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3protocolTff7b72.Td2a8ffmake_empty_fileTb4b4b4(Te6edf3safeTb4b4b4, Te6edf3digestTb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)
Tff7b72return

Te6edf3metadata Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fffilepathTa5d6ff"Tb4b4b4: Te6edf3safeTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Tb4b4b4(Te6edf3digest Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3file_sizeTb4b4b4,
Tb4b4b4}

Te6edf3peer_id Tff7b72= Tff7b72selfTff7b72.Td2a8ff_peer_keyTb4b4b4(Te6edf3linkTb4b4b4) Tff7b72or Ta5d6ff"Ta5d6ffunknownTa5d6ff"

Tff7b72def Td2a8ffconcludedTb4b4b4(Te6edf3resourceTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Tffa657hasattrTb4b4b4(Te6edf3resourceTb4b4b4, Ta5d6ff"Ta5d6ffdataTa5d6ff"Tb4b4b4) Tff7b72and Tffa657hasattrTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffdataTb4b4b4, Ta5d6ff"Ta5d6ffcloseTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3resourceTff7b72.Td2a8ffdataTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72finallyTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3handle Tff7b72= Tffa657openTb4b4b4(Te6edf3full_pathTb4b4b4, Ta5d6ff"Ta5d6ffrbTa5d6ff"Tb4b4b4)
Te6edf3resource Tff7b72= Te6edf3RNSTff7b72.Td2a8ffResourceTb4b4b4(
Te6edf3handleTb4b4b4,
Te6edf3linkTb4b4b4,
Te6edf3metadataTff7b72=Te6edf3metadataTb4b4b4,
Te6edf3auto_compressTff7b72=Tff7b72TrueTb4b4b4,
Te6edf3callbackTff7b72=Te6edf3concludedTb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffprogressTb4b4b4(Te6edf3resTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_sync_progressTb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4,
Ta5d6ff"Ta5d6ffdirectionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffsendTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: Te6edf3resTff7b72.Td2a8ffget_progressTb4b4b4(Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffpeer_idTa5d6ff"Tb4b4b4: Te6edf3peer_idTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3resourceTff7b72.Td2a8ffprogress_callbackTb4b4b4(Te6edf3progressTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_resourcesTb4b4b4[Te6edf3keyTb4b4b4] Tff7b72= Te6edf3resource
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffSend failed for Tffd700{Te6edf3safeTffd700}Ta5d6ff: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72def Td2a8ff_handle_delta_requestTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Te6edf3peer_blocks Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fflocal_blocksTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4[Tb4b4b4]
Tff7b72if Tff7b72not Te6edf3filepathTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffreadTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3peer_blocksTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Te6edf3full_path Tff7b72= Te6edf3resolve_under_rootTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72return

Tff7b72if Tff7b72not Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3full_pathTb4b4b4)Tb4b4b4:
Tff7b72return

Te6edf3key Tff7b72= Tff7b72selfTff7b72.Td2a8ff_begin_outgoingTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72if Te6edf3key Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return

Te6edf3local_blocks Tff7b72= Te6edf3hash_blocksTb4b4b4(Te6edf3full_pathTb4b4b4)
T8b949e# Only accept string hashes from the peer.
Te6edf3safe_peer_blocks Tff7b72= Tb4b4b4[Te6edf3b Tff7b72for Te6edf3b Tff7b72in Te6edf3peer_blocks Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3bTb4b4b4, Tffa657strTb4b4b4)Tb4b4b4]
Te6edf3blocks_to_send Tff7b72= Te6edf3differing_block_numsTb4b4b4(Te6edf3local_blocksTb4b4b4, Te6edf3safe_peer_blocksTb4b4b4)
Tff7b72if Tffa657lenTb4b4b4(Te6edf3blocks_to_sendTb4b4b4) Tff7b72== Tffa657lenTb4b4b4(Te6edf3local_blocksTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_handle_file_requestTb4b4b4(Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4}Tb4b4b4, Te6edf3linkTb4b4b4)
Tff7b72return

Te6edf3info Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffgetTb4b4b4(Te6edf3safeTb4b4b4) Tff7b72or Tb4b4b4{Tb4b4b4}
Te6edf3digest Tff7b72= Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4) Tff7b72or Te6edf3hash_fileTb4b4b4(Te6edf3full_pathTb4b4b4)
Te6edf3size Tff7b72= Te6edf3infoTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4)
Tff7b72if Te6edf3size Tff7b72is Tff7b72NoneTb4b4b4:
Te6edf3size Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffgetsizeTb4b4b4(Te6edf3full_pathTb4b4b4)

Te6edf3payload Tff7b72= Te6edf3build_delta_payloadTb4b4b4(Te6edf3full_pathTb4b4b4, Te6edf3blocks_to_sendTb4b4b4, Te6edf3BLOCK_SIZETb4b4b4)
Te6edf3metadata Tff7b72= Tb4b4b4{
Ta5d6ff"Ta5d6fffilepathTa5d6ff"Tb4b4b4: Te6edf3safeTff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4: Tb4b4b4(Te6edf3digest Tff7b72or Ta5d6ff"Ta5d6ff"Tb4b4b4)Tff7b72.Td2a8ffencodeTb4b4b4(Ta5d6ff"Ta5d6ffutf-8Ta5d6ff"Tb4b4b4)Tb4b4b4,
Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffdeltaTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffblocksTa5d6ff"Tb4b4b4: Te6edf3blocks_to_sendTb4b4b4,
Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4: Te6edf3sizeTb4b4b4,
Tb4b4b4}

Te6edf3tmp Tff7b72= Te6edf3tempfileTff7b72.Td2a8ffNamedTemporaryFileTb4b4b4(Te6edf3prefixTff7b72=Ta5d6ff"Ta5d6ff.rns-delta-Ta5d6ff"Tb4b4b4, Te6edf3deleteTff7b72=Tff7b72FalseTb4b4b4)
Te6edf3tmp_path Tff7b72= Te6edf3tmpTff7b72.Td2a8ffname
Tff7b72tryTb4b4b4:
Te6edf3tmpTff7b72.Td2a8ffwriteTb4b4b4(Te6edf3payloadTb4b4b4)
Te6edf3tmpTff7b72.Td2a8ffflushTb4b4b4(Tb4b4b4)
Te6edf3tmpTff7b72.Td2a8ffseekTb4b4b4(T79c0ff0Tb4b4b4)
Tff7b72except Tf85149ExceptionTb4b4b4:
Te6edf3tmpTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3tmp_pathTb4b4b4)
Tff7b72raise

Tff7b72def Td2a8ffconcludedTb4b4b4(Te6edf3resourceTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3tmpTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3tmp_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72tryTb4b4b4:
Te6edf3RNSTff7b72.Td2a8ffResourceTb4b4b4(
Te6edf3tmpTb4b4b4,
Te6edf3linkTb4b4b4,
Te6edf3metadataTff7b72=Te6edf3metadataTb4b4b4,
Te6edf3callbackTff7b72=Te6edf3concludedTb4b4b4,
Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffDelta send failed for Tffd700{Te6edf3safeTffd700}Ta5d6ff: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Te6edf3tmpTff7b72.Td2a8ffcloseTb4b4b4(Tb4b4b4)
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffunlinkTb4b4b4(Te6edf3tmp_pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_end_outgoingTb4b4b4(Te6edf3keyTb4b4b4)

Tff7b72def Td2a8ff_on_resource_advertTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3advertisementTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffenabledTb4b4b4:
Te6edf3sender Tff7b72= Te6edf3advertisementTff7b72.Td2a8fflinkTff7b72.Td2a8ffget_remote_identityTb4b4b4(Tb4b4b4)
Tff7b72if Te6edf3sender Tff7b72is Tff7b72NoneTb4b4b4:
Tff7b72return Tff7b72False
Tff7b72return Tff7b72selfTff7b72.Td2a8ffpermissionsTff7b72.Td2a8ffcheckTb4b4b4(Te6edf3senderTff7b72.Td2a8ffhashTb4b4b4, Ta5d6ff"Ta5d6ffwriteTa5d6ff"Tb4b4b4)
Tff7b72return Tff7b72True
Tff7b72except Tf85149ExceptionTb4b4b4:
Tff7b72return Tff7b72False

Tff7b72def Td2a8ff_on_resource_startedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3resourceTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72def Td2a8ffprogressTb4b4b4(Te6edf3resTb4b4b4)Tb4b4b4:
Te6edf3path Tff7b72= Tff7b72None
Tff7b72if Te6edf3resTff7b72.Td2a8ffmetadata Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3resTff7b72.Td2a8ffmetadataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3path Tff7b72= Te6edf3protocolTff7b72.Td2a8ffdecode_metadata_valueTb4b4b4(Te6edf3resTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilepathTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_sync_progressTb4b4b4,
Tb4b4b4{
Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3pathTb4b4b4,
Ta5d6ff"Ta5d6ffdirectionTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffreceiveTa5d6ff"Tb4b4b4,
Ta5d6ff"Ta5d6ffprogressTa5d6ff"Tb4b4b4: Te6edf3resTff7b72.Td2a8ffget_progressTb4b4b4(Tb4b4b4)Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)

Te6edf3resourceTff7b72.Td2a8ffprogress_callbackTb4b4b4(Te6edf3progressTb4b4b4)

Tff7b72def Td2a8ff_on_resource_concludedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3resourceTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72if Te6edf3resourceTff7b72.Td2a8ffstatus Tff7b72!= Te6edf3RNSTff7b72.Td2a8ffResourceTff7b72.Td2a8ffCOMPLETETb4b4b4:
Te6edf3filepath Tff7b72= Tff7b72None
Tff7b72if Te6edf3resourceTff7b72.Td2a8ffmetadata Tff7b72and Tffa657isinstanceTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffmetadataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3protocolTff7b72.Td2a8ffdecode_metadata_valueTb4b4b4(
Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilepathTa5d6ff"Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3filepathTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_incomingTff7b72.Td2a8ffpopTb4b4b4(Te6edf3filepathTb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffIncoming resource failed status=Tffd700{Te6edf3resourceTff7b72.Td2a8ffstatusTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72return

Tff7b72if Tff7b72not Te6edf3resourceTff7b72.Td2a8ffmetadata Tff7b72or Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffmetadataTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72if Ta5d6ff"Ta5d6fffilepathTa5d6ff" Tff7b72not Tff7b72in Te6edf3resourceTff7b72.Td2a8ffmetadataTb4b4b4:
Tff7b72return

Te6edf3filepath Tff7b72= Te6edf3protocolTff7b72.Td2a8ffdecode_metadata_valueTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffilepathTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3expected_hash Tff7b72= Tb4b4b4(
Te6edf3protocolTff7b72.Td2a8ffdecode_metadata_valueTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)Tb4b4b4) Tff7b72or Tff7b72None
Tb4b4b4)
Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3expected_hashTb4b4b4, Tffa657strTb4b4b4) Tff7b72and Tff7b72not Te6edf3expected_hashTff7b72.Td2a8ffstripTb4b4b4(Tb4b4b4)Tb4b4b4:
Te6edf3expected_hash Tff7b72= Tff7b72None
Te6edf3mode Tff7b72= Te6edf3protocolTff7b72.Td2a8ffdecode_metadata_valueTb4b4b4(Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffmodeTa5d6ff"Tb4b4b4)Tb4b4b4) Tff7b72or Ta5d6ff"Ta5d6fffullTa5d6ff"
Te6edf3expected_size Tff7b72= Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsizeTa5d6ff"Tb4b4b4)
Te6edf3blocks Tff7b72= Te6edf3resourceTff7b72.Td2a8ffmetadataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffblocksTa5d6ff"Tb4b4b4) Tff7b72or Tb4b4b4[Tb4b4b4]

Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3resourceTff7b72.Td2a8fflinkTb4b4b4, Ta5d6ff"Ta5d6ffwriteTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_incomingTff7b72.Td2a8ffpopTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(
Ta5d6ff"Ta5d6ffRejected resource: no write permission or unidentified peerTa5d6ff"Tb4b4b4,
Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4,
Tb4b4b4)
Tff7b72return

Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3blocksTb4b4b4, Tffa657listTb4b4b4)Tb4b4b4:
Tff7b72raise Tf85149ValueErrorTb4b4b4(Ta5d6ff"Ta5d6ffinvalid delta block listTa5d6ff"Tb4b4b4)
Te6edf3safe_blocks Tff7b72= Tb4b4b4[
Te6edf3b Tff7b72for Te6edf3b Tff7b72in Te6edf3blocks Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3bTb4b4b4, Tffa657intTb4b4b4) Tff7b72and Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3bTb4b4b4, Tffa657boolTb4b4b4)
Tb4b4b4]
Te6edf3commit_received_fileTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4,
Te6edf3safeTb4b4b4,
Te6edf3modeTff7b72=Ta5d6ff"Ta5d6ffdeltaTa5d6ff" Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6ffdeltaTa5d6ff" Tff7b72else Ta5d6ff"Ta5d6fffullTa5d6ff"Tb4b4b4,
Te6edf3resource_dataTff7b72=Te6edf3resourceTff7b72.Td2a8ffdataTb4b4b4,
Te6edf3block_numsTff7b72=Te6edf3safe_blocks Tff7b72if Te6edf3mode Tff7b72== Ta5d6ff"Ta5d6ffdeltaTa5d6ff" Tff7b72else Tff7b72NoneTb4b4b4,
Te6edf3expected_hashTff7b72=Te6edf3expected_hashTb4b4b4,
Te6edf3expected_sizeTff7b72=Tffa657intTb4b4b4(Te6edf3expected_sizeTb4b4b4) Tff7b72if Te6edf3expected_size Tff7b72is Tff7b72not Tff7b72None Tff7b72else Tff7b72NoneTb4b4b4,
Te6edf3require_hashTff7b72=Tff7b72TrueTb4b4b4,
Tb4b4b4)
Te6edf3info Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffupdate_from_pathTb4b4b4(Te6edf3safeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_incomingTff7b72.Td2a8ffpopTb4b4b4(Te6edf3safeTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_file_updatedTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4, Ta5d6ff"Ta5d6ffinfoTa5d6ff"Tb4b4b4: Te6edf3infoTb4b4b4}Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_broadcast_updateTb4b4b4(Te6edf3safeTb4b4b4, Te6edf3exclude_linkTff7b72=Te6edf3resourceTff7b72.Td2a8fflinkTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffReceived Tffd700{Te6edf3safeTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_INFOTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_incomingTff7b72.Td2a8ffpopTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4, Tff7b72NoneTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffFailed to commit Tffd700{Te6edf3filepathTffd700}Ta5d6ff: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_errorTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6fferrorTa5d6ff"Tb4b4b4: Tffa657strTb4b4b4(Te6edf3excTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3filepathTb4b4b4}Tb4b4b4)

Tff7b72def Td2a8ff_handle_empty_fileTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Te6edf3expected_hash Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3filepathTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffwriteTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Te6edf3create_empty_fileTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Te6edf3full Tff7b72= Te6edf3resolve_under_rootTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Te6edf3actual Tff7b72= Te6edf3hash_fileTb4b4b4(Te6edf3fullTb4b4b4)
Tff7b72if Te6edf3expected_hash Tff7b72and Te6edf3actual Tff7b72!= Te6edf3expected_hashTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3fullTb4b4b4)
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffEmpty file hash mismatch for Tffd700{Te6edf3safeTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_WARNINGTb4b4b4)
Tff7b72return
Te6edf3info Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffupdate_from_pathTb4b4b4(Te6edf3safeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_file_updatedTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4, Ta5d6ff"Ta5d6ffinfoTa5d6ff"Tb4b4b4: Te6edf3infoTb4b4b4}Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_broadcast_updateTb4b4b4(Te6edf3safeTb4b4b4, Te6edf3exclude_linkTff7b72=Te6edf3linkTb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffEmpty file handle failed: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_ERRORTb4b4b4)

Tff7b72def Td2a8ff_handle_file_updateTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Te6edf3peer_info Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffinfoTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3filepath Tff7b72or Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3peer_infoTb4b4b4, Tffa657dictTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffwriteTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72return
Te6edf3local Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffgetTb4b4b4(Te6edf3safeTb4b4b4)
Te6edf3action Tff7b72= Te6edf3decide_sync_actionTb4b4b4(Te6edf3localTb4b4b4, Te6edf3peer_infoTb4b4b4)
Tff7b72if Te6edf3action Tff7b72== Ta5d6ff"Ta5d6ffrequest_fullTa5d6ff"Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_request_fileTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72elif Te6edf3action Tff7b72== Ta5d6ff"Ta5d6ffrequest_deltaTa5d6ff"Tb4b4b4:
Te6edf3full Tff7b72= Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffjoinTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffexistsTb4b4b4(Te6edf3fullTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_request_deltaTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72elseTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_request_fileTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3safeTb4b4b4)

Tff7b72def Td2a8ff_handle_file_deletionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3dataTb4b4b4: Tffa657dictTb4b4b4, Te6edf3linkTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3filepath Tff7b72= Te6edf3dataTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4)
Tff7b72if Tff7b72not Te6edf3filepathTb4b4b4:
Tff7b72return
Tff7b72if Tff7b72not Tff7b72selfTff7b72.Td2a8ff_require_permTb4b4b4(Te6edf3linkTb4b4b4, Ta5d6ff"Ta5d6ffdeleteTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72tryTb4b4b4:
Te6edf3safe Tff7b72= Te6edf3normalize_relpathTb4b4b4(Tffa657strTb4b4b4(Te6edf3filepathTb4b4b4)Tb4b4b4)
Te6edf3full Tff7b72= Te6edf3resolve_under_rootTb4b4b4(Tff7b72selfTff7b72.Td2a8ffsync_directoryTb4b4b4, Te6edf3safeTb4b4b4)
Tff7b72except Te6edf3PathJailErrorTb4b4b4:
Tff7b72return
Tff7b72if Te6edf3osTff7b72.Td2a8ffpathTff7b72.Td2a8ffisfileTb4b4b4(Te6edf3fullTb4b4b4)Tb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149OSErrorTb4b4b4)Tb4b4b4:
Te6edf3osTff7b72.Td2a8ffremoveTb4b4b4(Te6edf3fullTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffremove_fileTb4b4b4(Te6edf3safeTb4b4b4)
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_file_deletedTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3safeTb4b4b4}Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_broadcast_deletionTb4b4b4(Te6edf3safeTb4b4b4, Te6edf3exclude_linkTff7b72=Te6edf3linkTb4b4b4)

Tff7b72def Td2a8ff_broadcast_updateTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3filepathTb4b4b4: Tffa657strTb4b4b4, Te6edf3exclude_linkTff7b72=Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3info Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffgetTb4b4b4(Te6edf3filepathTb4b4b4)
Tff7b72if Tff7b72not Te6edf3infoTb4b4b4:
Tff7b72return
Te6edf3payload Tff7b72= Te6edf3protocolTff7b72.Td2a8ffmake_file_updateTb4b4b4(Te6edf3filepathTb4b4b4, Te6edf3infoTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3links Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3link Tff7b72in Te6edf3linksTb4b4b4:
Tff7b72if Te6edf3link Tff7b72is Te6edf3exclude_link Tff7b72or Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72!= Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3payloadTb4b4b4)

Tff7b72def Td2a8ff_broadcast_deletionTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3filepathTb4b4b4: Tffa657strTb4b4b4, Te6edf3exclude_linkTff7b72=Tff7b72NoneTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3payload Tff7b72= Te6edf3protocolTff7b72.Td2a8ffmake_file_deletionTb4b4b4(Te6edf3filepathTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3links Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffvaluesTb4b4b4(Tb4b4b4)Tb4b4b4)
Tff7b72for Te6edf3link Tff7b72in Te6edf3linksTb4b4b4:
Tff7b72if Te6edf3link Tff7b72is Te6edf3exclude_link Tff7b72or Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72!= Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_sendTb4b4b4(Te6edf3linkTb4b4b4, Te6edf3payloadTb4b4b4)

Tff7b72def Td2a8ff_announce_loopTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3last Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ff_stop_eventTff7b72.Td2a8ffwaitTb4b4b4(T79c0ff10Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72- Te6edf3last Tff7b72>Tff7b72= Tff7b72selfTff7b72.Td2a8ff_announce_intervalTb4b4b4:
Tff7b72with Te6edf3contextlibTff7b72.Td2a8ffsuppressTb4b4b4(Tf85149ExceptionTb4b4b4)Tb4b4b4:
Tff7b72if Tff7b72selfTff7b72.Td2a8ffdestination Tff7b72is Tff7b72not Tff7b72NoneTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffdestinationTff7b72.Td2a8ffannounceTb4b4b4(Tb4b4b4)
Te6edf3last Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)

Tff7b72def Td2a8ff_monitor_loopTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ff_stop_eventTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3SCAN_INTERVALTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_monitor_onceTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffMonitor error: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)

Tff7b72def Td2a8ff_monitor_onceTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Te6edf3previous Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsnapshotTb4b4b4(Tb4b4b4)
Te6edf3current Tff7b72= Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffscanTb4b4b4(Tb4b4b4)
Te6edf3old_paths Tff7b72= Tffa657setTb4b4b4(Te6edf3previousTb4b4b4)
Te6edf3new_paths Tff7b72= Tffa657setTb4b4b4(Te6edf3currentTb4b4b4)
Te6edf3added Tff7b72= Te6edf3new_paths Tff7b72- Te6edf3old_paths
Te6edf3removed Tff7b72= Te6edf3old_paths Tff7b72- Te6edf3new_paths
Te6edf3modified Tff7b72= Tb4b4b4[
Te6edf3path
Tff7b72for Te6edf3path Tff7b72in Tb4b4b4(Te6edf3old_paths Tff7b72& Te6edf3new_pathsTb4b4b4)
Tff7b72if Te6edf3previousTb4b4b4[Te6edf3pathTb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4) Tff7b72!= Te6edf3currentTb4b4b4[Te6edf3pathTb4b4b4]Tff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffhashTa5d6ff"Tb4b4b4)
Tb4b4b4]
Tff7b72if Tff7b72not Tb4b4b4(Te6edf3added Tff7b72or Te6edf3removed Tff7b72or Te6edf3modifiedTb4b4b4)Tb4b4b4:
Tff7b72return
Tff7b72selfTff7b72.Td2a8ffinventoryTff7b72.Td2a8ffsaveTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3path Tff7b72in Te6edf3addedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_broadcast_updateTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_file_updatedTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffinfoTa5d6ff"Tb4b4b4: Te6edf3currentTb4b4b4[Te6edf3pathTb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffreasonTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffaddedTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3path Tff7b72in Te6edf3modifiedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_broadcast_updateTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(
Tff7b72selfTff7b72.Td2a8ffon_file_updatedTb4b4b4,
Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffinfoTa5d6ff"Tb4b4b4: Te6edf3currentTb4b4b4[Te6edf3pathTb4b4b4]Tb4b4b4, Ta5d6ff"Ta5d6ffreasonTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffmodifiedTa5d6ff"Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72for Te6edf3path Tff7b72in Te6edf3removedTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_broadcast_deletionTb4b4b4(Te6edf3pathTb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_emitTb4b4b4(Tff7b72selfTff7b72.Td2a8ffon_file_deletedTb4b4b4, Tb4b4b4{Ta5d6ff"Ta5d6ffpathTa5d6ff"Tb4b4b4: Te6edf3pathTb4b4b4, Ta5d6ff"Ta5d6ffreasonTa5d6ff"Tb4b4b4: Ta5d6ff"Ta5d6ffremovedTa5d6ff"Tb4b4b4}Tb4b4b4)

Tff7b72def Td2a8ff_reconnect_loopTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72while Tff7b72not Tff7b72selfTff7b72.Td2a8ff_stop_eventTff7b72.Td2a8ffwaitTb4b4b4(Te6edf3RECONNECT_BASE_INTERVALTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_reconnect_onceTb4b4b4(Tb4b4b4)
Tff7b72except Tf85149Exception Tff7b72as Te6edf3excTb4b4b4:
Te6edf3RNSTff7b72.Td2a8fflogTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffReconnect error: Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLOG_DEBUGTb4b4b4)

Tff7b72def Td2a8ff_reconnect_onceTb4b4b4(Tff7b72selfTb4b4b4) Tff7b72-Tff7b72> Tff7b72NoneTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Te6edf3desired Tff7b72= Tffa657listTb4b4b4(Tff7b72selfTff7b72.Td2a8ff_desired_peersTb4b4b4)
Te6edf3connected Tff7b72= Tffa657setTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3peer_idTb4b4b4, Te6edf3link Tff7b72in Tff7b72selfTff7b72.Td2a8ff_linksTff7b72.Td2a8ffitemsTb4b4b4(Tb4b4b4)Tb4b4b4:
Tff7b72if Te6edf3linkTff7b72.Td2a8ffstatus Tff7b72in Tb4b4b4(Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffACTIVETb4b4b4, Te6edf3RNSTff7b72.Td2a8ffLinkTff7b72.Td2a8ffHANDSHAKETb4b4b4)Tb4b4b4:
Te6edf3connectedTff7b72.Td2a8ffaddTb4b4b4(Te6edf3peer_idTb4b4b4)

Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72for Te6edf3peer_id Tff7b72in Te6edf3desiredTb4b4b4:
Tff7b72if Te6edf3peer_id Tff7b72in Te6edf3connectedTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTff7b72.Td2a8ffpopTb4b4b4(Te6edf3peer_idTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72continue
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3peer_id Tff7b72in Tff7b72selfTff7b72.Td2a8ff_connect_attemptsTb4b4b4:
Tff7b72continue
Te6edf3next_at Tff7b72= Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTff7b72.Td2a8ffgetTb4b4b4(Te6edf3peer_idTb4b4b4, T79c0ff0Tb4b4b4)
Tff7b72if Te6edf3now Tff7b72< Te6edf3next_atTb4b4b4:
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ff_connect_attemptsTff7b72.Td2a8ffaddTb4b4b4(Te6edf3peer_idTb4b4b4)

Tff7b72def Td2a8ffjobTb4b4b4(Te6edf3targetTff7b72=Te6edf3peer_idTb4b4b4)Tb4b4b4:
Tff7b72tryTb4b4b4:
Te6edf3result Tff7b72= Tff7b72selfTff7b72.Td2a8ffconnect_peerTb4b4b4(Te6edf3targetTb4b4b4, Te6edf3timeoutTff7b72=Te6edf3PATH_TIMEOUT_DEFAULTTb4b4b4)
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72if Te6edf3resultTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffokTa5d6ff"Tb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTff7b72.Td2a8ffpopTb4b4b4(Te6edf3targetTb4b4b4, Tff7b72NoneTb4b4b4)
Tff7b72elseTb4b4b4:
Te6edf3prev Tff7b72= Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTff7b72.Td2a8ffgetTb4b4b4(
Te6edf3targetTb4b4b4,
Te6edf3RECONNECT_BASE_INTERVALTb4b4b4,
Tb4b4b4)
Te6edf3delay Tff7b72= Tffa657minTb4b4b4(
Tffa657maxTb4b4b4(Te6edf3prev Tff7b72* T79c0ff2Tb4b4b4, Te6edf3RECONNECT_BASE_INTERVALTb4b4b4)Tb4b4b4,
Te6edf3RECONNECT_MAX_INTERVALTb4b4b4,
Tb4b4b4)
Tff7b72selfTff7b72.Td2a8ff_reconnect_backoffTb4b4b4[Te6edf3targetTb4b4b4] Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4) Tff7b72+ Te6edf3delay
Tff7b72finallyTb4b4b4:
Tff7b72with Tff7b72selfTff7b72.Td2a8ff_lockTb4b4b4:
Tff7b72selfTff7b72.Td2a8ff_connect_attemptsTff7b72.Td2a8ffdiscardTb4b4b4(Te6edf3targetTb4b4b4)

Te6edf3threadingTff7b72.Td2a8ffThreadTb4b4b4(Te6edf3targetTff7b72=Te6edf3jobTb4b4b4, Te6edf3daemonTff7b72=Tff7b72TrueTb4b4b4)Tff7b72.Td2a8ffstartTb4b4b4(Tb4b4b4)


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────